package com.oa.gform.client.ui;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.InsertPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;

/**
 * Implementazione di un fieldset che contine una tabella 
 * Utilizzabile anche con ui:binder
 * <p>
 * <img class='gallery' src='doc-files/VerticalPanel.png'/>
 * </p>
 */
public class GButtonPanel extends ComplexPanel implements HasAlignment, InsertPanel {

	private int spacing = 2;
	private Element tr = DOM.createTR();
	private Element table, body,extTable,extBody,extTr,extTd1,extTd2 ;
	private HorizontalAlignmentConstant horzAlign = ALIGN_DEFAULT;
	private VerticalAlignmentConstant vertAlign = ALIGN_MIDDLE;

	/**
	 * Crea un nuovo field set basato su due colonne
	 */
	public GButtonPanel() {
		tr = DOM.createTR();
		extTable = DOM.createTable();
		DOM.setElementProperty(extTable,"width","100%");
		extBody = DOM.createTBody();
		table = DOM.createTable();
		body = DOM.createTBody();
		extTr = DOM.createTR();
		extTd1 = createAlignedTd();
		extTd2 = createAlignedTd();
		DOM.appendChild(extTable, extBody);
		DOM.appendChild(extBody, extTr);
		DOM.appendChild(extTr, extTd1);
		DOM.appendChild(extTr, extTd2);
		setCellHorizontalAlignment(extTd2, ALIGN_RIGHT);
		
		DOM.appendChild(extTd2, table);
		DOM.setElementProperty(getTable(), "cellSpacing", "2");
		DOM.setElementProperty(getTable(), "cellPadding", "2");
		setElement(extTable);
		DOM.appendChild(table, body);
		
	}
	
	@Override
	public void add(Widget w) {
			
		Element td = createAlignedTd();
		DOM.appendChild(tr, td);
		DOM.appendChild(getBody(), tr);
		add(w, td);
	}


	/**
	 * Gets the amount of spacing between this panel's cells.
	 * 
	 * @return the inter-cell spacing, in pixels
	 */
	public int getSpacing() {
		return spacing;
	}

	/**
	 * Sets the width of the border to be applied to all cells in this panel.
	 * This is particularly useful when debugging layouts, in that it allows you
	 * to see explicitly the cells that contain this panel's children.
	 * 
	 * @param width
	 *            the width of the panel's cell borders, in pixels
	 */
	public void setBorderWidth(int width) {
		DOM.setElementProperty(table, "border", "" + width);
	}

	/**
	 * Sets the height of the cell associated with the given widget, related to
	 * the panel as a whole.
	 * 
	 * @param w
	 *            the widget whose cell height is to be set
	 * @param height
	 *            the cell's height, in CSS units
	 */
	public void setCellHeight(Widget w, String height) {
		Element td = getWidgetTd(w);
		if (td != null) {
			td.setPropertyString("height", height);
		}
	}

	/**
	 * Sets the horizontal alignment of the given widget within its cell.
	 * 
	 * @param w
	 *            the widget whose horizontal alignment is to be set
	 * @param align
	 *            the widget's horizontal alignment, as defined in
	 *            {@link HasHorizontalAlignment}.
	 */
	public void setCellHorizontalAlignment(Widget w, HorizontalAlignmentConstant align) {
		Element td = getWidgetTd(w);
		if (td != null) {
			setCellHorizontalAlignment(td, align);
		}
	}

	/**
	 * Sets the vertical alignment of the given widget within its cell.
	 * 
	 * @param w
	 *            the widget whose vertical alignment is to be set
	 * @param align
	 *            the widget's vertical alignment, as defined in
	 *            {@link HasVerticalAlignment}.
	 */
	public void setCellVerticalAlignment(Widget w, VerticalAlignmentConstant align) {
		Element td = getWidgetTd(w);
		if (td != null) {
			setCellVerticalAlignment(td, align);
		}
	}

	/**
	 * Sets the width of the cell associated with the given widget, related to
	 * the panel as a whole.
	 * 
	 * @param w
	 *            the widget whose cell width is to be set
	 * @param width
	 *            the cell's width, in CSS units
	 */
	public void setCellWidth(Widget w, String width) {
		Element td = getWidgetTd(w);
		if (td != null) {
			td.setPropertyString("width", width);
		}
	}

	/**
	 * Sets the amount of spacing between this panel's cells.
	 * 
	 * @param spacing
	 *            the inter-cell spacing, in pixels
	 */
	public void setSpacing(int spacing) {
		this.spacing = spacing;
		DOM.setElementPropertyInt(table, "cellSpacing", spacing);
	}

	protected Element getBody() {
		return body;
	}

	protected Element getTable() {
		return table;
	}

	protected void setCellHorizontalAlignment(Element td, HorizontalAlignmentConstant align) {
		DOM.setElementProperty(td, "align", align.getTextAlignString());
	}

	protected void setCellVerticalAlignment(Element td, VerticalAlignmentConstant align) {
		DOM.setStyleAttribute(td, "verticalAlign", align.getVerticalAlignString());
	}

	Element getWidgetTd(Widget w) {
		if (w.getParent() != this) {
			return null;
		}
		return DOM.getParent(w.getElement());
	}


	public HorizontalAlignmentConstant getHorizontalAlignment() {
		return horzAlign;
	}

	public VerticalAlignmentConstant getVerticalAlignment() {
		return vertAlign;
	}

	public void insert(Widget w, int beforeIndex) {
		checkIndexBoundsForInsertion(beforeIndex);

		Element tr = DOM.createTR();
		Element td = createAlignedTd();
		DOM.appendChild(tr, td);

		/*
		 * The case where we reinsert an already existing child is tricky.
		 * 
		 * For the WIDGET, it ultimately removes first and inserts second, so we
		 * have to adjust the index within ComplexPanel.insert(). But for the
		 * DOM, we insert first and remove second, which means we DON'T need to
		 * adjust the index.
		 */
		DOM.insertChild(getBody(), tr, beforeIndex);
		insert(w, td, beforeIndex, false);
	}

	@Override
	public boolean remove(Widget w) {
		/*
		 * Get the TR to be removed before calling super.remove() because
		 * super.remove() will detach the child widget's element from its
		 * parent.
		 */
		Element td = DOM.getParent(w.getElement());
		boolean removed = super.remove(w);
		if (removed) {
			DOM.removeChild(getBody(), DOM.getParent(td));
		}
		return removed;
	}

	/**
	 * Sets the default horizontal alignment to be used for widgets added to
	 * this panel. It only applies to widgets added after this property is set.
	 * 
	 * @see HasHorizontalAlignment#setHorizontalAlignment(HasHorizontalAlignment.HorizontalAlignmentConstant)
	 */
	public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
		horzAlign = align;
	}

	/**
	 * Sets the default vertical alignment to be used for widgets added to this
	 * panel. It only applies to widgets added after this property is set.
	 * 
	 * @see HasVerticalAlignment#setVerticalAlignment(HasVerticalAlignment.VerticalAlignmentConstant)
	 */
	public void setVerticalAlignment(VerticalAlignmentConstant align) {
		vertAlign = align;
	}

	/**
	 * <b>Affected Elements:</b>
	 * <ul>
	 * <li>-# = the cell at the given index.</li>
	 * </ul>
	 * 
	 * @see UIObject#onEnsureDebugId(String)
	 */
	@Override
	protected void onEnsureDebugId(String baseID) {
		super.onEnsureDebugId(baseID);
		int numChildren = getWidgetCount();
		for (int i = 0; i < numChildren; i++) {
			ensureDebugId(getWidgetTd(getWidget(i)), baseID, "" + i);
		}
	}

	private Element createAlignedTd() {
		Element td = DOM.createTD();
		setCellHorizontalAlignment(td, horzAlign);
		setCellVerticalAlignment(td, vertAlign);
		return td;
	}
}
